package com.my12306.common.util.quartz.scheduler;

import com.my12306.common.model.po.ScheduleJobPo;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author:苏牧夕
 * @Date:2020/5/29 3:06
 * @Version 1.0
 */
@Component
@Slf4j
public class ScheduleUtils {
    @Autowired
    private SchedulerAdapter schedulerAdapter;

    /**
     * 获取一个任务的唯一标识key
     *
     * @param jobName
     * @param groupName
     * @param jobId
     * @return
     */
    private static JobKey getJobKey(String jobName, String groupName, Long jobId) {
        return JobKey.jobKey(jobName + jobId, groupName + jobId);
    }

    /**
     * 获取用户组的定时任务唯一标识key
     *
     * @param jobId
     * @return
     */
    public static JobKey getUserJobKey(Long jobId) {
        return getJobKey(SchedulerJobConstant.JOB_NAME, SchedulerJobConstant.JOB_USER_GROUP, jobId);
    }

    /**
     * 获取用户组的定时任务唯一标识key
     *
     * @param jobId
     * @return
     */
    private static JobKey getSysJobKey(Long jobId) {
        return getJobKey(SchedulerJobConstant.JOB_NAME, SchedulerJobConstant.JOB_SYS_GROUP, jobId);
    }

    /**
     * 获取触发器的唯一标识key
     *
     * @param jobName
     * @param groupName
     * @param jobId
     * @return
     */
    private static TriggerKey getTriggerKey(String jobName, String groupName, Long jobId) {
        return TriggerKey.triggerKey(jobName + jobId, groupName + jobId);
    }

    /**
     * 获取用户的触发器
     *
     * @param jobId
     * @return
     */
    private static TriggerKey getUserTriggerKey(Long jobId) {
        return getTriggerKey(SchedulerJobConstant.TRIGGER_NAME, SchedulerJobConstant.JOB_USER_GROUP, jobId);
    }

    /**
     * 获取系统组的触发器
     *
     * @param jobId
     * @return
     */
    private static TriggerKey getSysTriggerKey(Long jobId) {
        return getTriggerKey(SchedulerJobConstant.TRIGGER_NAME, SchedulerJobConstant.JOB_SYS_GROUP, jobId);
    }

    /**
     * 对外提供的的任务添加接口
     *
     * @param baseScheduler
     * @param scheduler
     * @param scheduleJobPo
     * @return
     * @
     */
    public Boolean addJob(BaseScheduler baseScheduler, Scheduler scheduler, ScheduleJobPo scheduleJobPo) {
        Long id = scheduleJobPo.getJobId();
        if (id != null) {
            if (scheduleJobPo.getType() == SchedulerJobConstant.SYS_TYPE) {
                try {
                    addSysJob(baseScheduler, scheduler, scheduleJobPo);
                } catch (SchedulerException e) {
                    return false;
                }
            } else {
                log.info("========>进入用户组！");
                addUserJob(baseScheduler, scheduler, scheduleJobPo);
            }
            return true;
        } else {
            return false;
        }
    }

    /**
     * 对外任务修改接口
     *
     * @param baseScheduler
     * @param scheduler
     * @param scheduleJobPo
     * @
     */
    public Boolean updateJob(BaseScheduler baseScheduler, Scheduler scheduler, ScheduleJobPo scheduleJobPo) {
        if (scheduleJobPo.getJobId() == null) return false;
        Boolean flag = false;
        if (scheduleJobPo.getType() == SchedulerJobConstant.SYS_TYPE) {
            try {
                flag = updateSysJob(baseScheduler, scheduler, scheduleJobPo);
            } catch (SchedulerException e) {
                flag = false;
            }
        } else {
            try {
                flag = updateUserJob(baseScheduler, scheduler, scheduleJobPo);
            } catch (SchedulerException e) {
                flag = false;
            }
        }
        if (flag) {
            if (scheduleJobPo.getShowStatus() == JobOperateEnum.PAUSE.getValue()) {
                pauseJob(baseScheduler, scheduler, scheduleJobPo.getJobId(), scheduleJobPo.getType());
            }
        }
        return flag;
    }

    /**
     * 对外开放的暂停接口
     *
     * @param baseScheduler
     * @param scheduler
     * @param jobId         任务id
     * @param type          任务类型：系统类型、用户类型
     * @return
     */
    public Boolean pauseJob(BaseScheduler baseScheduler, Scheduler scheduler, Long jobId, Integer type) {
        if (type.equals(SchedulerJobConstant.USER_TYPE)) {
            return pauseUserJob(baseScheduler, scheduler, jobId);
        } else {
            return pauseSysJob(baseScheduler, scheduler, jobId);
        }
    }

    /**
     * 暂停所有定时任务
     *
     * @param baseScheduler
     * @param scheduler
     */
    public void pauseAllJob(BaseScheduler baseScheduler, Scheduler scheduler) {
        schedulerAdapter.pauseAllJob(baseScheduler, scheduler);
    }

    /**
     * 对外开放的唤醒任务接口
     *
     * @param baseScheduler
     * @param scheduler
     * @param jobId
     * @param type          任务类型 ：1.系统，2.用户
     * @return
     */
    public Boolean resumeJob(BaseScheduler baseScheduler, Scheduler scheduler, Long jobId, Integer type) {
        if (type.equals(SchedulerJobConstant.USER_TYPE)) {
            System.out.println("usertype:" + type);
            return resumeUserJob(baseScheduler, scheduler, jobId);
        } else {
            System.out.println("systype:" + type);
            return resumeSysJob(baseScheduler, scheduler, jobId);
        }
    }

    /**
     * 对外提供的开发的唤醒所有任务的接口
     * 唤醒所有被暂停的定时任务
     *
     * @param baseScheduler 自定义的任务调度类
     * @param scheduler     任务调度器
     */
    public void resumeAllJob(BaseScheduler baseScheduler, Scheduler scheduler) {
        schedulerAdapter.resumeAllJob(baseScheduler, scheduler);
    }

    /**
     * 对外提供的删除任务接口
     *
     * @param baseScheduler
     * @param scheduler     调度器
     * @param jobId         任务id
     * @param type          任务类型
     * @return
     */
    public Boolean deleteJob(BaseScheduler baseScheduler, Scheduler scheduler, Long jobId, Integer type) {
        if (type.equals(SchedulerJobConstant.USER_TYPE)) {
            return deleteUserJob(baseScheduler, scheduler, jobId);
        } else {
            return deleteSysJob(baseScheduler, scheduler, jobId);
        }
    }

    /**
     * 对外开放根据jobkeys删除所有定时任务
     *
     * @param baseScheduler
     * @param scheduler
     * @param scheduleJobPos
     * @return
     */
    public Boolean deleteAllJob(BaseScheduler baseScheduler, Scheduler scheduler, List<ScheduleJobPo> scheduleJobPos) {
        if (scheduleJobPos == null) return false;
        List<JobKey> jobKeys = scheduleJobPos.parallelStream().filter(x -> x.getType() != null).map(x -> {
            JobKey jobKey = null;
            if (x.getType().equals(SchedulerJobConstant.USER_TYPE)) {
                jobKey = getUserJobKey(x.getJobId());
                return jobKey;
            } else {
                jobKey = getSysJobKey(x.getJobId());
                return jobKey;
            }
        }).collect(Collectors.toList());

        schedulerAdapter.deleteAllJob(baseScheduler, scheduler, jobKeys);
        return true;
    }

    /**
     * 不对外提供的用户组的任务添加接口
     *
     * @param baseScheduler
     * @param scheduler
     * @param scheduleJobPo
     * @return
     * @
     */
    private Boolean addUserJob(BaseScheduler baseScheduler, Scheduler scheduler, ScheduleJobPo scheduleJobPo) {
        Long id = scheduleJobPo.getJobId();
        if (id != null) {
            try {
                log.info("=============>进入addUserJob");
                schedulerAdapter.addJob(baseScheduler, scheduler, scheduleJobPo, getUserJobKey(id), getUserTriggerKey(id));
            } catch (SchedulerException e) {
                log.info("===============>出现异常了");
                return false;
            }
            return true;
        } else {
            return false;
        }
    }

    /**
     * 不对外提供添加系统组的任务接口
     *
     * @param baseScheduler
     * @param scheduler
     * @param scheduleJobPo
     * @return
     * @
     */
    private Boolean addSysJob(BaseScheduler baseScheduler, Scheduler scheduler, ScheduleJobPo scheduleJobPo) throws SchedulerException {
        Long id = scheduleJobPo.getJobId();
        if (id != null) {
            schedulerAdapter.addJob(baseScheduler, scheduler, scheduleJobPo, getSysJobKey(id), getSysTriggerKey(id));
            return true;
        } else {
            return false;
        }
    }

    /**
     * 内部的任务添加接口
     *
     * @param baseScheduler
     * @param scheduler
     * @param scheduleJobPo
     * @param jobKey
     * @param triggerKey
     * @
     */
    private void addJob(BaseScheduler baseScheduler, Scheduler scheduler, ScheduleJobPo scheduleJobPo, JobKey jobKey, TriggerKey triggerKey) throws SchedulerException {
        schedulerAdapter.addJob(baseScheduler, scheduler, scheduleJobPo, jobKey, triggerKey);
    }

    /**
     * 不对外提供的用户组的修改任务接口
     *
     * @param baseScheduler
     * @param scheduler
     * @param scheduleJobPo 任务对象
     * @
     */
    private Boolean updateUserJob(BaseScheduler baseScheduler, Scheduler scheduler, ScheduleJobPo scheduleJobPo) throws SchedulerException {
        Long jobId = scheduleJobPo.getJobId();
        if (jobId == null) return false;
        updateJob(baseScheduler, scheduler, scheduleJobPo, getUserTriggerKey(jobId));
        return true;
    }

    /**
     * 不对外提供修改系统的任务组的任务接口
     *
     * @param baseScheduler
     * @param scheduler
     * @param scheduleJobPo 任务对象
     * @
     */
    private Boolean updateSysJob(BaseScheduler baseScheduler, Scheduler scheduler, ScheduleJobPo scheduleJobPo) throws SchedulerException {
        Long jobId = scheduleJobPo.getJobId();
        if (jobId == null) return false;
        updateJob(baseScheduler, scheduler, scheduleJobPo, getSysTriggerKey(jobId));
        return true;
    }

    /**
     * 内部任务修改接口
     *
     * @param baseScheduler
     * @param scheduler
     * @param scheduleJobPo
     * @param triggerKey
     * @
     */
    private void updateJob(BaseScheduler baseScheduler, Scheduler scheduler, ScheduleJobPo scheduleJobPo, TriggerKey triggerKey) throws SchedulerException {
        schedulerAdapter.updateJob(baseScheduler, scheduler, scheduleJobPo, triggerKey);
    }

    /**
     * 不对外提供的用户删除任务接口
     *
     * @param baseScheduler 自定义任务调度类
     * @param scheduler     任务调度器
     * @param jobId         任务id
     * @return
     */
    private Boolean deleteUserJob(BaseScheduler baseScheduler, Scheduler scheduler, Long jobId) {
        if (jobId != null) {
            schedulerAdapter.deleteJob(baseScheduler, scheduler, getUserJobKey(jobId), getUserTriggerKey(jobId));
            return true;
        }
        return false;
    }

    /**
     * 不对外提供的删除系统组的任务接口
     *
     * @param baseScheduler 自定义任务调度类
     * @param scheduler     任务调度器
     * @param jobId         任务id
     * @return
     */
    private Boolean deleteSysJob(BaseScheduler baseScheduler, Scheduler scheduler, Long jobId) {
        if (jobId != null) {
            schedulerAdapter.deleteJob(baseScheduler, scheduler, getUserJobKey(jobId), getUserTriggerKey(jobId));
            return true;
        }
        return false;
    }

    /**
     * 内部删除任务接口
     *
     * @param baseScheduler
     * @param scheduler
     * @param jobKey
     * @param triggerKey
     */
    private void deleteJob(BaseScheduler baseScheduler, Scheduler scheduler, JobKey jobKey, TriggerKey triggerKey) {
        schedulerAdapter.deleteJob(baseScheduler, scheduler, jobKey, triggerKey);
    }

    /**
     * 不对外开放的用户任务组的暂停接口
     *
     * @param baseScheduler 自定义的任务调度类
     * @param scheduler     任务调到去
     * @param jobId         任务id
     * @return
     */
    private Boolean pauseUserJob(BaseScheduler baseScheduler, Scheduler scheduler, Long jobId) {
        if (jobId != null) {
            schedulerAdapter.pauseJob(baseScheduler, scheduler, getUserJobKey(jobId));
            return true;
        }
        return false;
    }

    /**
     * 不对外开放的系统任务组的暂停接口
     *
     * @param baseScheduler 自定义任务调度类
     * @param scheduler     任务调度器
     * @param jobId         任务的id
     * @return
     */
    private Boolean pauseSysJob(BaseScheduler baseScheduler, Scheduler scheduler, Long jobId) {
        if (jobId != null) {
            schedulerAdapter.pauseJob(baseScheduler, scheduler, getSysJobKey(jobId));
            return true;
        }
        return false;
    }

    /**
     * 不对外开放的暂停接口
     *
     * @param baseScheduler
     * @param scheduler
     * @param jobKey
     */
    private void pauseJob(BaseScheduler baseScheduler, Scheduler scheduler, JobKey jobKey) {
        schedulerAdapter.pauseJob(baseScheduler, scheduler, jobKey);
    }

    /**
     * 不对外提供的用户暂停任务接口
     * 根据任务id,唤醒暂停的定时任务
     *
     * @param baseScheduler 自定义的任务调度类
     * @param scheduler     任务调度器
     * @param jobId         任务id;
     * @return
     */
    private Boolean resumeUserJob(BaseScheduler baseScheduler, Scheduler scheduler, Long jobId) {
        System.out.println("jobid=" + jobId);
        if (jobId != null) {
            resumeJob(baseScheduler, scheduler, getUserJobKey(jobId));
            return true;
        }
        return false;
    }

    /**
     * 不对外提供的系统任务的暂停任务接口
     * 根据任务id,唤醒暂停的定时任务
     *
     * @param baseScheduler 自定义的任务调度类
     * @param scheduler     任务调度器
     * @param jobId         任务id;
     * @return
     */
    private Boolean resumeSysJob(BaseScheduler baseScheduler, Scheduler scheduler, Long jobId) {
        if (jobId != null) {
            resumeJob(baseScheduler, scheduler, getSysJobKey(jobId));
            return true;
        }
        return false;
    }

    /**
     * 不不对外开放
     * 根据定时任务的Jobkey唤醒任务
     *
     * @param baseScheduler 自定义的任务调度类
     * @param scheduler     任务调度器
     * @param jobKey        任务的Jobkey
     */
    private void resumeJob(BaseScheduler baseScheduler, Scheduler scheduler, JobKey jobKey) {
        schedulerAdapter.resumeJob(baseScheduler, scheduler, jobKey);
    }

    /**
     * 内部枚举类
     */
    public static enum JobOperateEnum {
        START(1, "启动"),
        PAUSE(2, "暂停"),
        DELETE(3, "删除");
        private final Integer value;
        private final String desc;

        JobOperateEnum(final Integer value, final String desc) {
            this.value = value;
            this.desc = desc;
        }

        public Integer getValue() {
            return value;
        }

        public String getDesc() {
            return desc;
        }
    }

    /**
     * 静态内部常量类
     *
     * @Author:苏牧夕
     * @Date:2020/5/27 23:50
     * @Version 1.0
     */
    class SchedulerJobConstant {
        /**
         * 定时任务唯一标识key的前缀
         */
        public final static String JOB_NAME = "ilife_job_";
        /**
         * 触发器的唯一标识key的前缀
         */
        public final static String TRIGGER_NAME = "ilife_trigger_";
        /**
         * 定时任务用户组
         */
        public final static String JOB_USER_GROUP = "ilife_user_";
        /**
         * 定时任务系统组
         */
        private final static String JOB_SYS_GROUP = "ilife_sys_";
        /**
         * 系统类型
         */
        private final static int SYS_TYPE = 1;
        /**
         * 用户类型
         */
        private final static int USER_TYPE = 2;
    }


}
